package graybox;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import fetcher.SparkConfiguration;
import others.Global;
import shellInterface.UserSubmitInterface_test;



public class CallPythonWindows  {
	public int threadID;
	public Process daemonProcess;
	OutputStream outStream=null;
	InputStream inStream =null;
	InputStream errorStream=null;

	
	public int pythonDaemonPredict(SparkConfiguration para, ArrayList<String> groupNameList) throws Exception{
		int ret = this.pythonDaemonPredict(para.toString(),groupNameList);
		return ret;
	}
	
	/*
	 * 调用pythonDaemonProcess进行数据预测
	 * 回归方法
	 * 函数返回以ms为单位
	 * 目前只返回三个预测组中一个的信息
	 */
	public int pythonDaemonPredict(String predictInputString,ArrayList<String> groupNameList) throws Exception {

		long startMili = System.currentTimeMillis();
		long endMili=-1;
		ArrayList<Integer> retList =new ArrayList<Integer>();
		if (!this.daemonProcess.isAlive()) {
			Scanner s = new Scanner(errorStream);
			while (s.hasNextLine()) {
				String line = s.nextLine();
				System.err.println(line);
				
			}
			s.close();
			throw new Exception("daemon 进程已经终结，无法正常工作 优化程序退出");
		}
		try {

			
			if(Global.DEBUG_FLAG){
				String str= null;
				for (String s : groupNameList){
					str=str+s;
				}
				System.out.println(str+"\t输入:\t"+predictInputString);
				System.out.println("发送给python预测模块的字符串"+predictInputString);
			}

			//发送输入
			//outStream.write("48 1 0 3072 5120 1 0 12 2 0 0.7\n".getBytes());
			outStream.write(predictInputString.getBytes());
			outStream.flush();// 必须通过flush将字节流清空
		} catch (IOException e) {
			e.printStackTrace();
		}
		//返回输出
		Scanner s = new Scanner(inStream);
		while (s.hasNextLine()) {
			String line = s.nextLine();
			if(Global.DEBUG_FLAG) System.out.println("python 返回值："+line);
			if (line.contains("[prediction results]")){
				//预测结果精确到ms计，是一个整形
				retList.add(Integer.parseInt(line.split("\t")[1]));
				retList.add(Integer.parseInt(line.split("\t")[2]));
				retList.add(Integer.parseInt(line.split("\t")[3]));
				
/*				switch (groupName) {
				case "ret1":
					ret= Integer.parseInt(line.split("\t")[1]);
					//String aString=line.split("\t")[1];
					//System.err.println(line.split("\t")[1]);
					break;
				case "ret2":
					ret= Integer.parseInt(line.split("\t")[2]);
					break;
				case "ret3":
					ret= Integer.parseInt(line.split("\t")[3]);
					break;
	
				default:
					System.err.println("callPythonWindows预测函数，错误的组名");
					break;
				}*/
	
				endMili = System.currentTimeMillis();
				if (Global.DEBUG_FLAG) System.out.println("预测时间开销："+(endMili-startMili)+"ms");
				if (Global.DEBUG_FLAG) System.out.println("返回结果："+retList.get(0));
				return retList.get(0);
			}
		}
		s.close();
		return retList.get(0);
	}

	// 单线程调用脚本，但是生成一个动态的守护进程
	public int pythonDaemonStart(String pythonScriptPath, String[] params) throws InterruptedException {
		File file = new File(pythonScriptPath);
		if (!file.exists()) {
			UserSubmitInterface_test.UIErr("python脚本不存在！:"+pythonScriptPath);
			return -1;
		}
		// 拷贝了 命令+路径+params -》command
		String[] command = Arrays.copyOf(new String[] { "python", pythonScriptPath }, params.length + 2);
		System.arraycopy(params, 0, command, 2, params.length);
		try {
			File workDir=new File("."+File.separator+"PythonFiles"+File.separator);
			this.daemonProcess = Runtime.getRuntime().exec(command, null, null);// 实际上可以通过dir
																						// 来调整working
																						// dir,注意 sub process 指的是执行command 的shell！ 所以command + work Path 必须配合才行 
			/*
			// python输入流 OutputStream
			OutputStream outStream = pythonDaemonProcess.getOutputStream();
			outStream.write("48 1 0 3072 5120 1 0 12 2 0 0.5\n".getBytes());
			outStream.flush();// 必须通过flush将字节流清空
			// python输出流
			InputStream inStream = pythonDaemonProcess.getInputStream();
			Scanner s = new Scanner(inStream);
			while (s.hasNextLine()) {
				long tmpEndMili = System.currentTimeMillis();
				String line = s.nextLine();
				System.out.println(line);
				res.add(line);
			}
			this.pythonDaemonProcess.destroy();
			this.pythonDaemonProcess.waitFor();// 这意味着守护进程的终止 } catch
			*/
			 this.outStream = this.daemonProcess.getOutputStream();
			 this.inStream = this.daemonProcess.getInputStream();
			 this.errorStream=this.daemonProcess.getErrorStream();
		} catch (IOException e) {
			e.printStackTrace();
		};

		if (this.daemonProcess.isAlive()){
			UserSubmitInterface_test.UIOutPut("启动Python daemon 成功:" +String.join(" ", command));
			return 0;
		}
		else {
			UserSubmitInterface_test.UIErr("启动Python daemon 失败:"+String.join(" ", command));
			return 1;
		}

	}

	/*
	 * 单线程调用脚本并等待脚本结束
	 * 
	 * */
	public int pythonRun(String pythonScriptPath, String[] params) throws InterruptedException {
		File file = new File(pythonScriptPath);
		if (!file.exists()) {
			System.out.println("python脚本不存在！"+pythonScriptPath);
			System.err.println(file.getAbsolutePath());
			return -1;
		}
		// 拷贝了 命令+路径+params -》command
		String[] command = Arrays.copyOf(new String[] { "python", pythonScriptPath }, params.length + 2);
		System.arraycopy(params, 0, command, 2, params.length);
		Process process=null;
		ArrayList<String> res = new ArrayList<>();
		long startMili = System.currentTimeMillis();// 当前时间对应的毫秒数
		try {
			process = Runtime.getRuntime().exec(command, null, null);
			@SuppressWarnings("resource")
			Scanner scanner = new Scanner(process.getInputStream());
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
				res.add(line);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
		long endMili = System.currentTimeMillis();
		int retValue=process.waitFor();
		System.out.println("调用Python脚本结束：\t"  +String.join(" ",command) + "\t 用时：\t" + (endMili - startMili) + "ms\tID\t:"
				+ this.threadID);
		return retValue;
	}

	public void pythonDaemonEnd() {
		this.daemonProcess.destroy();
	}

	public InputStream getInStream() {
		return inStream;
	}
	
/*	@Override
	
	 * run函数是线程的全部生命过程，调用完了线程就跪
	 * 以下的函数都不会被实际执行，只是留一个纪念，最后还是使用windows下的process 代替了java自己产生的Thread
	 * 因为进行windows调用的时候早晚会产生Process，而且我们也不需要多个这样的process 同时运行 ，所以最后都无所谓的……
	 * Thread 应该是主要用于执行自己写的代码用的
	 
	public void run() {// run方法是一个必须被重载的方法，所以不能期待他有返回值和参数
		// TODO Auto-generated method stub
		System.out.println("[Thread Started!\t]" + "ID:\t" + this.threadID);
		System.out.println(System.currentTimeMillis());
	}

	@SuppressWarnings("static-access")
	public CallPythonWindows() {
		//多线程运行模式
		this.threadID = this.threadIDCount;
		this.threadIDCount++;
		this.thread = new Thread(this, "Thread Name");
		this.thread.start();//调用run函数

	}

	public CallPythonWindows(String a) {
		// 这是单线程运行模式
	}*/
	
}
